﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
using SDT.CodeSystem;
using SDT.CrawlSystem.Servers.Filters;

namespace SDT.CrawlSystem.Servers
{
    /// <summary>
    /// Written by TungNX
    /// </summary>
    public sealed partial class WebCrawler
    {
        private IList<UrlLoader> UrlLoaders = new List<UrlLoader>();

        private DateTime DataFileLastWriteTime = DateTime.MinValue;
        private bool MustReloadData()
        {
            var F = new FileInfo(dataFile);
            if (!F.Exists)
                return false;

            var ret = DataFileLastWriteTime != F.LastWriteTime;
            DataFileLastWriteTime = F.LastWriteTime;
            return ret;
        }

        private void LoadData()
        {
            if (MustReloadData())
            {
                #region Clear data before reloading
                ClearWork();
                UrlLoaders.Clear();
                #endregion

                #region Load data file into XmlDocument
                var d = new XmlDocument();
                var w = (new FileInfo(DataFile)).OpenText();
                var r = XmlReader.Create(w);
                
                //Modified Date : 03/10/2010
                //Author : TungNX
                //Try catch loi
                try
                {
                    d.Load(r);

                    r.Close();
                    w.Close();
                #endregion

                    #region Custom log file
                    var n = d.SelectSingleNode("Channels/LogFile");
                    lock (Logger)
                        Logger.FilePath = n != null && n.InnerText.Trim().Length > 0 ? n.InnerText.Trim() : Global.Instance.LogFile;
                    #endregion

                    #region Custom interval
                    n = d.SelectSingleNode("Channels/Interval");
                    interval = n != null && n.InnerText.Trim().Length > 0 ? Convert.ToInt32(n.InnerText.Trim()) : Global.Instance.Interval;
                    n = d.SelectSingleNode("Channels/WorkUnitInterval");
                    workUnitInterval = n != null && n.InnerText.Trim().Length > 0 ? Convert.ToInt32(n.InnerText.Trim()) : Global.Instance.WorkUnitInterval;
                    #endregion

                    lock (Logger)
                        Logger.AddEntry(String.Format("BEGIN LoadData({0})", DataFile));

                    #region Load channels
                    var l = d.GetElementsByTagName("Channel");
                    foreach (var i in l)
                        LoadData(i as XmlNode);
                    //load thêm thằng encoding nữa
                    #endregion

                    lock (Logger)
                    {
                        Logger.AddEntry("END LoadData");
                        Logger.Flush();
                    }
                }
                catch (Exception ex)
                {
                    lock (Logger)
                        Logger.AddEntry(String.Format("ERROR {0} - BEGIN LoadData({1})", ex.Message, DataFile));

                }


            }
        }

        /// <summary>
        /// Load channel node
        /// </summary>
        private void LoadData(XmlNode n)
        {
           
            #region Channel's attributes
            if (n.Attributes["Active"].Value != "1")
                return;
            var id = Convert.ToInt32(n.Attributes["Id"].Value);
            if (id == 0)
                return;
            var name = n.Attributes["Name"].Value;
            #endregion

            #region Encoding
            var enc = n.Attributes["Encoding"] != null && n.Attributes["Encoding"].Value != null ?
                Encoding.GetEncoding(n.Attributes["Encoding"].Value.Trim()) : Encoding.UTF8;
            #endregion

            // url loader
            var uLoader = new UrlLoader(n.SelectSingleNode("UrlLoader"));

            #region Load default filters
            // html filter
            var hF = n.SelectSingleNode("HtmlFilter") != null ? new Filter(n.SelectSingleNode("HtmlFilter")) : null;

            // title filter
            var tF = n.SelectSingleNode("TitleFilter") != null ? new Filter(n.SelectSingleNode("TitleFilter")) : null;

            //lead filter
            var lF = n.SelectSingleNode("LeadFilter") != null ? new Filter(n.SelectSingleNode("LeadFilter")) : null;

            // date filter
            var dF = n.SelectSingleNode("DateFilter") != null ? new DateFilter(n.SelectSingleNode("DateFilter")) : null;

            // content filter
            var conF = n.SelectSingleNode("ContentFilter") != null ? new Filter(n.SelectSingleNode("ContentFilter")) : null;
            #endregion

            #region Load pages
            var l = n.SelectNodes("Page");
            foreach (var p in l)

                LoadData(id, p as XmlNode, uLoader, hF, tF, dF, lF, conF, enc);
            
            #endregion
        }

        /// <summary>
        /// Load page node
        /// </summary>
        private void LoadData(int cid, XmlNode p, UrlLoader uLoader,
            IFilter hFilter, IFilter tFilter, IDateFilter dFilter, IFilter lFilter, IFilter conFilter,
            Encoding enc)
        {
            #region Page's attributes
            var id = Convert.ToInt32(p.Attributes["Id"].Value);
            var cityID = Convert.ToInt32(p.Attributes["CityID"].Value);
            var demandid = Convert.ToInt32(p.Attributes["DemandID"].Value);
            if (id == 0)
                return;
            #endregion

            #region Load local filters (if have)
            // html filter
            var hf = p.SelectSingleNode("HtmlFilter") != null ? new Filter(p.SelectSingleNode("HtmlFilter")) : hFilter;

            // title filter
            var tf = p.SelectSingleNode("TitleFilter") != null ? new Filter(p.SelectSingleNode("TitleFilter")) : tFilter;

            // date filter
            var df = p.SelectSingleNode("DateFilter") != null ? new DateFilter(p.SelectSingleNode("DateFilter"), enc) : dFilter;
            //Lead News
            var lf = p.SelectSingleNode("LeadFilter") != null ? new Filter(p.SelectSingleNode("LeadFilter")) : lFilter;

            // content filter
            var conf = p.SelectSingleNode("ContentFilter") != null ? new Filter(p.SelectSingleNode("ContentFilter")) : conFilter;
            #endregion

            UrlLoaders.Add(new UrlLoader(id, p.SelectSingleNode("UrlLoader"), uLoader, hf, tf, lf, df, conf,cityID,demandid, enc));
        }
    }
}